import autoit

class WinControl(object):
    '''
    AutoIt窗口相关操作

    :Attributes:
     - title: The title of the window .
     - text: The text of the window . Default is an empty string
    '''
    def __init__(self, title, text=''):
        self.title = title
        self.text = text

    def activate(self):
        '''
        激活指定的窗口(设置焦点到该窗口,使其成为活动窗口).

        :Returns:
            PID:窗口存在; 0:窗口不存在.

        :Example:
         - 例: win.activate()
        '''
        return autoit.win_activate(self.title, text=self.text)

    def close(self):
        '''
        关闭指定窗口.

        :Returns:
            1:成功; 0:窗口不存在.

        :Example:
         - 例: win.close()
        '''
        return autoit.win_close(self.title, text=self.text)

    def exists(self):
        '''
        检查指定的窗口是否存在.

        :Returns:
            1:窗口存在; 0:窗口不存在.

        :Example:
         - 例: win.exists()
        '''
        return autoit.win_exists(self.title, text=self.text)

    def get_pos(self):
        '''
        获取指定窗口的坐标位置和大小等属性.

        :Returns:
            Returns left, top, right, bottom    (x1,y1,x2,y2)

        :Example:
         - 例: left,top,right,bottom = win.get_pos()
        '''
        return autoit.win_get_pos(self.title, text=self.text)

    def get_process(self):
        '''
        获取指定窗口关联的进程ID(PID).

        :Returns:
            PID:成功, -1:失败.

        :Example:
         - 例: pid = win.get_process()
        '''
        return autoit.win_get_process(self.title, text=self.text)

    def get_text(self, buf_size=256):
        '''
        获取指定窗口中的文本.

        :Args:
         - buf_size: 获取的字符串最大长度，默认256

        :Returns:
            指定窗口里包含的文本:成功; 0:失败(没有匹配的窗口).

        :Example:
         - 例: text = win.get_text()
        '''
        return autoit.win_get_text(self.title, buf_size, text=self.text)

    def kill(self):
        '''
        强行关闭指定窗口.

        :Example:
         - 例: win.kill()
        '''
        return autoit.win_kill(self.title, text=self.text)

    def move(self, x, y, width, height):
        '''
        移动指定的窗口或调整窗口的大小.

        :Args:
         - x: X coordinate to move to.
         - y: Y coordinate to move to.
         - width: New width of the control.
         - height: New height of the control.

        :Returns:
            1:成功, 0:失败(窗口不存在).

        :Example:
         - 例: win.move(100,100,1024,612)
        '''
        return autoit.win_move(self.title, x, y, width, height, text=self.text)

    def set_state(self, flag):
        '''
        显示,隐藏,最小化,最大化或还原一个窗口.

        :Args:
         - flag: The "show" flag of the executed program:显示|最小化/隐藏|最大化|还原

        :Returns:
            1:成功, 0:失败(窗口不存在).

        :Example:
         - 例: win.set_state('最小化')
        '''
        return autoit.win_set_state(self.title, flag, text=self.text)

    def wait(self, timeout=5):
        '''
        暂停脚本的执行直至指定窗口存在(出现)为止.

        :Args:
         - timeout: 单位为秒.

        :Returns:
            PID:成功, 0:失败(超时).

        :Example:
         - 例: win.wait()
        '''
        return autoit.win_wait(self.title, timeout, text=self.text)

    def wait_active(self, timeout=5):
        '''
        暂停脚本的执行直至指定窗口被激活(成为活动状态)为止.

        :Args:
         - timeout: 单位为秒.

        :Returns:
            PID:成功, 0:失败(超时).

        :Example:
         - 例: win.wait_active()
        '''
        return autoit.win_wait_active(self.title, timeout, text=self.text)

    def wait_close(self, timeout=5):
        '''
        暂停脚本的执行直至所指定窗口不再存在为止.

        :Args:
         - timeout: 单位为秒.

        :Returns:
            1:成功, 0:失败(超时).

        :Example:
         - 例: win.wait_close()
        '''
        return autoit.win_wait_close(self.title, timeout, text=self.text)

    def wait_not_active(self, timeout=5):
        '''
        暂停脚本的执行直至指定窗口不是激活状态为止.

        :Args:
         - timeout: 单位为秒.

        :Returns:
            1:成功, 0:失败(超时).

        :Example:
         - 例: win.wait_not_active()
        '''
        return autoit.win_wait_not_active(self.title, timeout, text=self.text)

    def control_click(self, control, button="main", clicks=1):
        '''
        向指定控件发送鼠标点击命令.

        :Args:
         - control: 控件
         - button: 鼠标按键，默认为'main'
         - clicks: 点击次数，默认为1

        :Example:
         - 例: win.control_click('Button1','main',1)
        '''
        autoit.control_click(self.title, control, text=self.text, button=button, clicks=clicks)

    def control_command(self, control, command, extra="", buf_size=256):
        '''
        向指定控件发送命令.

        :Usages:
         - :params command, extra            ->:return
         - "IsVisible", ""                   ->1:可见; 0:不可见
         - "IsEnabled", ""                   ->1:可用; 0:禁用
         - "ShowDropDown", ""                ->弹出/下拉 组合框(ComboBox)的列表.
         - "HideDropDown", ""                ->收回/隐藏 组合框(ComboBox)的列表.
         - "AddString", "string"             ->在 ListBox 或 ComboBox 的编辑框后面附加指定字符串.
         - "DelString", 出现次序             ->删除在 ListBox 或 ComboBox 的编辑框中指定的字符串(从0开始).
         - "FindString", "string"            ->返回在 ListBox 或 ComboBox 的编辑框中与指定字符串匹配项目的出现次序(从0开始).
         - "SetCurrentSelection", 出现次序   ->通过指定出现次序(从0开始)把 ListBox 或 ComboBox 的当前选择项设为指定的项目.
         - "SelectString","string"           ->通过指定字符串把 ListBox 或 ComboBox 的当前选择项设为匹配字符串的项目.
         - "IsChecked", ""                   ->若目标按钮(复选框/单选框)被选中则返回值为1,否则为0.
         - "Check", ""                       ->使目标按钮(复选框/单选框)变为选中状态.
         - "UnCheck", ""                     ->使目标按钮(复选框/单选框)变为非选中状态.
         - "GetCurrentLine", ""              ->返回在目标编辑框中插入符(caret,光标)的所在行号.
         - "GetCurrentCol", ""               ->返回在目标编辑框中插入符(caret,光标)的所在列号.
         - "GetCurrentSelection", ""         ->返回 ListBox 或 ComboBox 控件当前选中的项目名.
         - "GetLineCount", ""                ->返回目标编辑框中的总行数.
         - "GetLine", 行号                   ->返回目标编辑框中指定行的文本内容.
         - "GetSelected", ""                 ->返回目标编辑框中的(用户用鼠标或其它方式)选定的文本.
         - "EditPaste", 'string'             ->在目标编辑框中插入符(caret)所在位置后插入指定字符串.
         - "CurrentTab", ""                  ->返回在 SysTabControl32 控件中当前显示的标签编号(从1开始).
         - "TabRight", ""                    ->使 SysTabControl32 控件切换到(右边的)下一个标签.
         - "TabLeft", ""                     ->使 SysTabControl32 控件切换到(左边的)下一个标签.
         - "SendCommandID", 命令 ID          ->模拟WM_COMMAND消息.通常用于ToolbarWindow32 控件(使用Au3Info的工具栏标签得到命令ID.)

        :Example:
         - 例1: win.control_command('ListBox1','IsVisible')
         - 例2: win.control_command('ListBox1','DelString',0)
         - 例3: win.control_command('ListBox1','GetLine',1)
         - 例4: win.control_command('ComboBox1','SelectString','香蕉')
        '''
        return autoit.control_command(self.title, control, command, buf_size, text=self.text, extra=extra)

    def control_listview(self, control, command, extra1, extra2="", buf_size=256):
        '''
        向指定的 ListView32 控件发送命令.

        :Usages:
         - :params command, extra1, extra2      ->:return
         - "DeSelect", 从[, 到]                 ->取消选定从"从"开始直到"到"的一个或多个项目.
         - "FindItem", "搜索字符串" [, 子项目]  ->返回与给定字符串匹配的项目的位置.若未找到指定字符串则返回值为 -1.
         - "GetItemCount"                       ->返回列表中项目的数量.
         - "GetSelected" [, 选项]               ->返回当前选中项目的位置.若 选项=0(默认)则只返回选中的第一个项目;若 选项=1 则返回由竖线"|"作为分隔符的所有选中项目,例如:"0|3|4|10".若没有选中任何项目则返回一个空字符串"".
         - "GetSelectedCount"                   ->返回选中项目的数量.
         - "GetSubItemCount"                    ->返回子项目的数量.
         - "GetText", 项目, 子项目              ->返回指定项目/子项目的文本.
         - "IsSelected", 项目                   ->若指定项目被选中则返回值为1,否则返回值为0.
         - "Select", 从[, 到]                   ->选中一个或多个项目(请参考第一个命令).
         - "SelectAll"                          ->选中所有项目.
         - "SelectClear"                        ->取消所有项目的选中状态.
         - "SelectInvert"                       ->切换当前的选中状态.
         - "ViewChange", "视图"                 ->切换当前的视图.可用的视图包括"list"(列表),"details"(详细信息),"smallicons"(小图标),"largeicons"(大图标).

        :Example:
         - 例: win.control_listview('ListView1','GetText','水果','香蕉')
        '''
        return autoit.control_list_view(self.title, control, command, buf_size, text=self.text, extra1=extra1,
                                        extra2=extra2)

    def control_disable(self, control):
        '''
        禁用或使某控件变成灰色不可用状态.

        :Args:
         - control: 控件

        :Returns:
            1:成功; 0:失败.

        :Example:
         - 例: win.control_disable('Button1')
        '''
        return autoit.control_disable(self.title, control, text=self.text)

    def control_enable(self, control):
        '''
        使灰色按钮/控件变为"可用"状态.

        :Args:
         - control: 控件

        :Returns:
            1:成功; 0:失败.

        :Example:
         - 例: win.control_enable('Button1')
        '''
        return autoit.control_enable(self.title, control, text=self.text)

    def control_focus(self, control):
        '''
        设置输入焦点到指定窗口的某个控件上.

        :Args:
         - control: 控件

        :Returns:
            1:成功; 0:失败.

        :Example:
         - 例: win.control_focus('Button1')
        '''
        return autoit.control_focus(self.title, control, text=self.text)

    def control_gettext(self, control):
        '''
        获取指定控件上的文本.

        :Args:
         - control: 控件

        :Returns:
            文本内容:成功; 空:失败.

        :Example:
         - 例: win.control_gettext('Button1')
        '''
        return autoit.control_get_text(self.title, control, text=self.text)

    def control_send(self, control, send_text, mode=0):
        '''
        向指定的控件发送字符串.

        :Args:
         - control: 控件
         - send_text: 输入的内容
         - mode: 0: 按特殊字符含义发送(默认); 1:原样发送.

        :Returns:
            1:成功; 0:失败(窗口/控件未找到).

        :Example:
         - 例: win.control_send('Button1','Enter')
        '''
        return autoit.control_send(self.title, control, send_text, mode, text=self.text)

    def control_settext(self, control, control_text):
        '''
        修改指定控件的文本.

        :Args:
         - control: 控件
         - control_text: 输入的内容

        :Returns:
            1:成功; 0:失败(窗口/控件未找到).

        :Example:
         - 例: win.control_settext('Text1', '苹果')
        '''
        return autoit.control_set_text(self.title, control, control_text, text=self.text)

    def control_treeview(self, control, command, extra, buf_size=256):
        '''
        发送一个命令到 TreeView32 控件.(子节点不好用*)

        :Usages:
         - params: command,extra        ->:return
         - "Check","项目"               ->选中一个项目 (如果项目支持选中,这里指项目带有选择框).
         - "Collapse","项目"            ->折叠一个项目节点,使它隐藏它的子项目.
         - "Exists","项目"              ->如果项目存在返回 1,否则返回 0.
         - "Expand","项目"              ->展开一个项目节点,使它显示它的子项目.
         - "GetItemCount","项目"        ->返回所选项目的子项目数量.
         - "GetSelected"[,使用索引]     ->返回当前所选项目的文本参考信息(如果使用索引设置为1将会返回所选项目索引位置).
         - "GetText","项目"             ->返回项目文本.
         - "IsChecked"                  ->返回项目选中状态. 1:被选中, 0:未被选中, -1:没要选择框.
         - "Select","项目"              ->选择一个项目.
         - "Uncheck","项目"             ->取消项目选中状态 (如果项目支持选中,这里指项目带有选择框).

        :Example:
         - 例1: win.control_treeview('TreeView1','Select','葡萄')
         - 例2: win.control_treeview('TreeView1','IsChecked')
        '''
        return autoit.control_tree_view(self.title, control, command, text=self.text, buf_size=buf_size, extra=extra)

    def statusbar_gettext(self, part=1, buf_size=256):
        '''
        获取标准状态栏控件的文本.

        :Args:
         - part: 要读取的状态栏编号，默认为1；1是第一个可能的部分，通常是包含有用消息的部分，
             如“准备就绪”、“正在加载”等
         - buf_size: 设置返回的内容最大长度

        :Returns:
            文本内容:成功; 空字符串:失败(无法读取文本).

        :Example:
         - 例: win.statusbar_gettext('正在加载')
        '''
        return autoit.statusbar_get_text(self.title, self.text, part, buf_size)

    def sendkeys(self, text):
        '''
        win的键盘输入事件

        :Args:
         - text: list支持组合键的键入，str支持字符串各字符分别键入

        :Example:
         - 例1: win.sendkeys(['Ctrl','a'])
         - 例2: win.sendkeys('send')
        '''
        # 特殊按键
        if isinstance(text, list):
            if len(text) == 1:
                autoit.send('{' + text[0].upper() + '}')
            else:
                # 组合键
                text = [item.upper() for item in text]
                ret = ''
                if 'CTRL' in text:
                    ret += '^'
                    text.remove('CTRL')
                if 'ALT' in text:
                    ret += '!'
                    text.remove('ALT')
                if 'SHIFT' in text:
                    ret += '+'
                    text.remove('SHIFT')
                if 'WIN' in text:
                    ret += '#'
                    text.remove('WIN')
                for item in text:
                    if len(item) == 1:
                        ret += item.lower()
                    else:
                        ret += '{' + item + '}'
                autoit.send(ret)
        # 字符串
        elif isinstance(text, str):
            autoit.send(text, mode=1)

if __name__ == '__main__':
    # import time
    # wc = WinControl("中国工商银行新一代网上银行 - Internet Explorer")
    # wc.activate()
    # wc.control_focus("[CLASS:ATL:Edit; INSTANCE:1]")
    # time.sleep(2)
    # wc.control_click("[CLASS:ATL:Edit; INSTANCE:1]")
    # time.sleep(2)
    # wc.sendkeys("123456")
    # wc.control_send("[CLASS:ATL:Edit; INSTANCE:1]","12345")

    wc = WinControl("中国工商银行新一代网上银行 - Internet Explorer")
    wc.activate()
    wc.control_focus("ATL:Edit1")
    wc.sendkeys("12345")
